package com.intelligentpension.kotlinbluetooth.bt

import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.os.Environment
import com.hjq.toast.ToastUtils
import com.intelligentpension.kotlinbluetooth.utils.ThreadUtils
import com.orhanobut.logger.Logger
import java.io.*
import java.util.*


/**
 * 版权：点赞 版权所有
 * author :赵航
 * @e-mail: zhaohangcn@gmail.com
 * time：2022/3/29
 * describe ：
 * 其中internal constructor
 */
open class BtBase internal constructor(private var mListener: Listener?) {
    val SPP_UUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")//经典蓝牙必须固定的UUID
    private val FILE_PATH = Environment.getExternalStorageDirectory().absolutePath + "/bluetooth/";
    private val FLAG_MEG: Int = 0//消息标记
    private val FLAG_FILE: Int = 1 //文件标记
    private var mSocket: BluetoothSocket? = null
    private var mOut: DataOutputStream? = null

    private var isRead: Boolean = false
    private var isSending: Boolean = false


    @SuppressLint("MissingPermission")
    fun loopRead(socket: BluetoothSocket) {
        mSocket = socket;
        try {
            Logger.e("=======蓝牙操作UI")
            if (mSocket == null) {
                Logger.e("=======蓝牙断开")
                return
            }
            if (!mSocket?.isConnected!!) {
                Logger.e("=======蓝牙再次连接之后")
                mSocket?.connect()
            }
            //连接蓝牙设备,返回
            notifyUi(Listener.CONNECTED, mSocket?.remoteDevice)
            mOut = DataOutputStream(mSocket?.outputStream)
            var input = DataInputStream(mSocket?.inputStream)
            isRead = true
            while (isRead) {
                when (input.readInt()) {
                    FLAG_MEG -> {
                        var msg: String = input.readUTF()//获取指定的信息
                        notifyUi(Listener.MSG, "接受短消息:$msg")
                    }
                    FLAG_FILE -> {
                        var file = File(FILE_PATH)
                        if (!file.exists()) {
                            file.mkdirs()
                        }

                        var fileName: String = input.readUTF()//文件名
                        var fileLen = input.readLong()//文件长度


                        //读取文件内容
                        var len: Long = 0
                        var r: Int
                        val b = ByteArray(4 * 1024)
                        var out = FileOutputStream(FILE_PATH + fileName)
                        notifyUi(Listener.MSG, "正在接收文件($fileName),请稍后...")
                        while (input.read(b).also { r = it } !== -1) {
                            out.write(b, 0, r)
                            len += r
                            if (len >= fileLen) break
                        }
                        notifyUi(Listener.MSG, "文件接收完成(存放在:$FILE_PATH)")
                        break
                    }
                }
            }

        } catch (e: Exception) {
            e.printStackTrace()
            closeSocket()
        }

    }

    /**
     * 关闭蓝牙通讯
     */
    open fun closeSocket() {
        try {
            isRead = false
            mSocket?.close()
            mOut?.close()
            notifyUi(Listener.DISCONNECTED, null)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 回调蓝牙消息
     */
    private fun notifyUi(connected: Int, obj: Any?) {
        ThreadUtils.executeMainThread {
            try {
                mListener?.socketNotify(connected, obj)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 关闭监听引用(例如释放对Activity的引用,避免内存泄漏)
     */
    fun unListener() {
        mListener = null
    }

    interface Listener {
        fun socketNotify(state: Int, obj: Any?)

        companion object {
            const val DISCONNECTED = 0
            const val CONNECTED = 1
            const val MSG = 2
        }
    }

    /**
     * 发送短信息
     */
    fun sendMsg(msg: String) {
        if (checkSend()) return
        isSending = true
        try {
            mOut?.writeInt(FLAG_MEG)
            mOut?.writeUTF(msg)
            mOut?.flush()
            notifyUi(Listener.MSG, "发送短消息: $msg")
        } catch (e: Exception) {
            closeSocket()
        }
        isSending = false
    }

    /**
     * 发送文件
     */
    fun sendFile(filePath: String) {
        if (checkSend()) return
        isSending = true
        ThreadUtils.executeSubThread {
            try {
                var input = FileInputStream(filePath)
                var file = File(filePath)
                mOut?.writeInt(FLAG_FILE)//文件标记
                mOut?.writeUTF(file.name)//文件名
                mOut?.writeLong(file.length())//文件长度

                var r: Int;
                var b = ByteArray(4 * 1024)
                notifyUi(Listener.MSG, "正在发送文件($filePath),请稍后...");
                while (input.read(b).also { r = it } != -1) {
                    mOut?.write(b, 0, r)
                }
                mOut?.flush()
                notifyUi(Listener.MSG, "问价发送完成");
            } catch (e: Exception) {
                e.printStackTrace()

                closeSocket()
            }
            isSending = false

        }
    }

    /**
     *查询当前是否正在发送文件
     */
    private fun checkSend(): Boolean {
        if (isSending) {
            ToastUtils.show("正在发送其他数据,请稍后再发...")
            return true
        }
        return false
    }

    /**
     * 查询当前设备是否与指定的设备连接
     */
    fun isConnected(dev: BluetoothDevice?): Boolean {
        val connected = mSocket != null && mSocket!!.isConnected
        return if (dev == null) connected else connected && mSocket!!.remoteDevice == dev
    }
}